package ruleengine;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

/**
 * Great fun to solve the hard level puzzles.
 * @author Seabook
 *
 */
public class RuleEngine {
	RuleComplier complier = new RuleComplier();

	public static void main(String[] args) {
		RuleEngine re = new RuleEngine();
		// String[] ruleSet1 = new String[] { "A<1", "B>2" };
		// String[] ruleSet2 = new String[] { "A>1", "BB1,2" };

		// String[] ruleSet1 = new String[] { "A<0" };
		// String[] ruleSet2 = new String[] { "A<0" };

		// String[] ruleSet1 = new String[] { "A==1", "X>=4", "F<1" };
		// String[] ruleSet2 = new String[] { "X>=5", "ZB2,9" };

		// String[] ruleSet1 = new String[] { "A<1", "B==2", "C>4", "D>=6",
		// "E<=9", "FB1,2", "J!=6" };
		// String[] ruleSet2 = new String[] { "E>9" };

		// String[] ruleSet1 = new String[] { "A<01", "B==2", "C>4", "D>=2",
		// "E<=9", "FB1,2", "J!=6" };
		// String[] ruleSet2 = new String[] { "A<9", "B>=2" };

//		String[] ruleSet1 = new String[] { "A<=9", "B<=9", "C<=9", "D<=9",
//				"E<=9", "F<=9", "G<=9" };
//		String[] ruleSet2 = new String[] { "H<=9", "I<=9", "J<=9", "K<=9",
//				"L<=9", "M<=9", "N<=9" };
		
		String[] ruleSet1 = new String[] { "KB-09,5", "K<3" };
		String[] ruleSet2 = new String[] { "Y>4" };

		System.out.println(re.countSets(ruleSet1, ruleSet2));
	}

	public String countSets(String[] ruleSet1, String[] ruleSet2) {
		for (String oneRule : ruleSet1) {
			complier.parseAndAdd(oneRule);
		}

		for (String oneRule : ruleSet2) {
			complier.parseAndAdd(oneRule);
		}

		Map<String, List<Integer>> rules = complier.rules;

		debugRules();

		long result = 1;
		for (Entry<String, List<Integer>> entry : rules.entrySet()) {
			int size = entry.getValue().size();
			if (size == 0)
				return "0";
			result *= size;
		}

		return String.valueOf(result);
	}

	public void debugRules() {
		for (Entry<String, List<Integer>> entry : complier.rules.entrySet()) {
			System.out.println(entry.getKey() + " --> "
					+ entry.getValue().toString());
		}
	}
}

class RuleComplier {
	private static final List<Integer> FULL_DATA_LIST = Arrays
			.asList(new Integer[] { -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0,
					1, 2, 3, 4, 5, 6, 7, 8, 9, 10 });

	Map<String, List<Integer>> rules = new HashMap<String, List<Integer>>();

	public void addRule(String key, List<Integer> value) {
		if (rules.containsKey(key)) {
			rules.get(key).retainAll(value);
		} else
			rules.put(key, value);
	}

	public void parseAndAdd(String rule) {
		String key = "";
		String operator = "";
		if (rule.contains("!="))
			operator = "!=";
		else if (rule.contains("=="))
			operator = "==";
		else if (rule.contains("<="))
			operator = "<=";
		else if (rule.contains(">="))
			operator = ">=";
		else if (rule.contains("<"))
			operator = "<";
		else if (rule.contains(">"))
			operator = ">";
		else if (rule.contains("B"))
			operator = "B";

		key = rule.substring(0, rule.indexOf(operator));

		if ("B".equals(operator)) {
			if (rule.startsWith("B")) {
				key = "B";
			}
		}

		List<Integer> datas = parseRuleKey(rule, operator);
		addRule(key, datas);

	}

	private List<Integer> parseRuleKey(String rule, String operator) {
		List<Integer> data = new ArrayList<Integer>(FULL_DATA_LIST);
		String dataStr = "";
		if ("B".equals(operator)) {
			if (rule.startsWith("B")) {
				dataStr = rule.substring(rule.indexOf(operator) + 2, rule
						.length());
			} else
				dataStr = rule.substring(rule.indexOf(operator) + 1, rule
						.length());

			String[] bDatas = dataStr.split(",");
			int posStart = Collections.binarySearch(data, Integer
					.valueOf(bDatas[0]));
			int posEnd = Collections.binarySearch(data, Integer
					.valueOf(bDatas[1]));
			data = data.subList(posStart, posEnd + 1);
		} else {
			dataStr = rule.substring(
					rule.indexOf(operator) + operator.length(), rule.length());
			int value = Integer.valueOf(dataStr);
			int pos = Collections.binarySearch(data, value);
			if ("!=".equals(operator)) {
				data.remove(Integer.valueOf(value));
			} else if ("<=".equals(operator)) {
				data = data.subList(0, pos + 1);
			} else if ("<".equals(operator)) {
				data = data.subList(0, pos);
			} else if (">=".equals(operator)) {
				data = data.subList(pos, data.size());
			} else if (">".equals(operator)) {
				data = data.subList(pos + 1, data.size());
			} else if ("==".equals(operator)) {
				data = new ArrayList<Integer>();
				data.add(value);
			}
		}

		return data;
	}
}